package cms_category

import (
	"context"
	"errors"
	"fmt"
	"gitee.com/binny_w/gin_starter/core"
	"gitee.com/binny_w/go-util"
	util2 "gitee.com/binny_w/go-util/v2"
	"github.com/gin-gonic/gin"
	"strings"
)

func Tree(ctx context.Context) (*util.Tree, error) {
	if ret, err := core.Cache.GetOrSingleDo("all-category-tree", func(k string, mc *util.MemCache) (any, error) {
		tree := util.NewTree()
		idsToDel := make([]any, 0)
		keysToDel := make([]any, 0)
		defer func() {
			if len(idsToDel) > 0 {
				_, _ = core.CmsCategory.DeleteByIds(ctx, idsToDel...)
				query := fmt.Sprintf(
					"UPDATE `%s` SET `category_key` = '' WHERE `category_key` IN (%s)",
					core.CmsArticle.Name,
					strings.TrimRight(strings.Repeat("?,", len(idsToDel)), ","),
				)
				_, _ = core.CmsArticle.Update(ctx, query, keysToDel...)
			}
		}()
		if err := core.CmsCategory.SelectWalk(ctx, func(_ context.Context, row *util2.MysqlRow) error {
			id := row.ToInt64("id")
			pKey := row.ToStr("p_key")
			item, _ := util.NewTreeItem(
				row.ToStr("key"),
				row.ToStr("label"),
				uint(row.ToInt64("rank")),
				gin.H{
					"id":    id,
					"p_key": pKey,
				},
			)
			if err := tree.AddItem(item, pKey); err != nil && errors.Is(err, util.ErrTreeParentNotFound) {
				idsToDel = append(idsToDel, id)
				keysToDel = append(keysToDel, item.Key)
			}
			return nil
		}, fmt.Sprintf("SELECT * FROM `%s` ORDER BY `created_at` ASC", core.CmsCategory.Name)); err != nil {
			return nil, err
		}
		mc.Set(k, tree, 1800)
		return tree, nil
	}); err != nil {
		return nil, err
	} else {
		return ret.(*util.Tree), nil
	}
}
